#ifndef TBLOCK_H
#define TBLOCK_H

#include "crossbit/common.h"
#include "crossbit/Exit.h"
#include "crossbit/VBlock.h"
#include <vector>

namespace crossbit {

	class TCache;

	class TBlock {
		public:
			friend class TCache;

			TBlock()
			{
				//modified by zhunan 2010-3-11
				tb_exits.reserve(GLOBAL::MAX_BLOCK_CHAIN_NUM * 3);
				run_count = 0;
				is_super_block = false;
			}

			virtual ~TBlock() 
			{ 
			}
			//added by zhunan 2010-3-11
			VBlock * VBlock_addr;
			// --------------------------------------------
			//		Basic Management
			// --------------------------------------------

			// Return size of the target code block
			XTUint32 getSize() const
			{ 
				return tb_size; 
			}

			// Return the entry address of the target code
			XTMemAddr enterAddr() const
			{ 
				return tb_tcode; 
			}

			// Return size of the target code block
			XTUint32 setSize(XTUint32 size)
			{ 
				tb_size = size; 
			}

			// -------------------------------------------------
			//		    Exit management
			// -------------------------------------------------

			//static const std::string EXITREASON2STR[4];

			// Return TBlock::Exit reference
			Exit &getExit(XTUint32 i)
			{
				if( i >= 0 && i < tb_exits.size() )
					return tb_exits[i];
				else
				{

					return tb_exits[-1];
				}
			}

			XTInt32 addExit( Exit e )
			{
				tb_exits.push_back(e);
				if( tb_exits.size() > GLOBAL::MAX_BLOCK_CHAIN_NUM * 2  ) 
					printf("ERROR==============\n"); 
				return tb_exits.size() - 1;
			}

			XTUint32 exitNums()
			{
				return tb_exits.size();	
			}

			// ----------------------------------------------
			//		relocation management
			// ----------------------------------------------

			void addRelocationPoint(XTUint32 where)
			{
				tb_relocations.push_back(where);
			}

			void relocate(XTUint32 offset);

			void setSPC( XTMemAddr spc )
			{
				tb_spc = spc;
			}

			XTMemAddr getSPC()
			{
				return tb_spc;
			}

			//Add by suntingtao for build superblock		
			bool isSupperBlock( void ){ return is_super_block; }
			void setSuperBlock( void ) { is_super_block = true; }
			XTUint32 getRunCount( void ) { return run_count; }
			void  setRunCount() 
			{//modify by zhunan 2010-3-11 
				++run_count;
				//if (run_count>100) exit;	// what a poly fuck! who added it?! 2010-4-12, zyc
				this->VBlock_addr->Add_Run_Count();
			}
			XTMemAddr getRunCountAddr( void ) { return (XTMemAddr)&run_count;}

		protected:

			// duplicate TBlock is not allowed
			TBlock(const TBlock &tblock) {}
			TBlock& operator=(const TBlock &tblock) { return *this; }

			std::vector<Exit> tb_exits;
			XTMemAddr tb_spc;
			XTMemAddr	tb_tcode;
			XTUint32	tb_size;

			std::vector<int> tb_relocations;

			//Added by suntingtao, to collect the run time of the of this block.
			XTUint32  run_count;
			bool 	  is_super_block;
	};

}
#endif
